
package convertTestsToJUnit;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Arrays;

import model.Filter;
import model.MethodDeclared;
import model.TestClusterBuilder;
import util.GAConfig;
import operations.AssignConstant;
import operations.CreateObject;
import operations.InvokeMethod;
import operations.Operation;
import ga.GAInfo;
import ga.Individual;

public class SimplifierStatic implements TestTransformation {
	public static final SimplifierStatic singleton = new SimplifierStatic();

	/**
	 * Returns a simplified copy of the test, removing invalid operations (statically analyzed)
	 * @return a simplified copy of the test
	 */
	@Override
	public Individual perform(Individual test,GAInfo gaInfo) {
		TestClusterBuilder TestCluster= gaInfo.getTestCluster();
		Map<String, String[]>  ref=TestCluster.getRefFactory();
		String[] refs = new String[ref.size()*2];
		int indx=0;
		for(String keyRef:ref.keySet()){
			for(int i=0;i<ref.get(keyRef).length;i++)
				refs[indx++]=ref.get(keyRef)[i];
		}
		/** initialized[i] true if the i-th reference is non-null */
		boolean[] initialized = new boolean[ref.size()*2];

		/** initializedNull[i] true if has been emitted "ref_i = null" */
		boolean[] initializedNull = new boolean[ref.size()*2];

		for(int i = 0; i < initialized.length; i++) initialized[i] = false;
		List<Operation> ops = new ArrayList<Operation>(test.getStatements().size());
		for(Operation op : test.getStatements()) {
			if(op instanceof AssignConstant) {
				AssignConstant ac = (AssignConstant) op;
				if(ac.getRefrence() != null) {
					initialized[Arrays.asList(refs).indexOf(ac.getRefrence())] = (ac.getValue() != null);
					initializedNull[Arrays.asList(refs).indexOf(ac.getRefrence())] = (ac.getValue() == null);
					ops.add(op);
				}
			}else if(op instanceof CreateObject) {
				CreateObject co = (CreateObject) op;
//				if(!checkInitializated(co.getConstructor().getInputTypes(), co.getValues(), initialized,refs)) continue;
//
//				initializeToNull(ops, co.getRef(), initialized, initializedNull);
				if(co.getRef() != null)
					initialized[Arrays.asList(refs).indexOf(co.getRef())] = true;

				ops.add(op);
			} else if(op instanceof InvokeMethod) {
				InvokeMethod in = (InvokeMethod) op;

//				if(!checkInitializated(in.getMethod().getParameterTypes(), in.getParams(), initialized)) continue;
//
				if(!((MethodDeclared) in.getMethod()).isStatic() && (in.getThis() == null || !initialized[Arrays.asList(refs).indexOf(in.getThis())])) continue;
				if(((MethodDeclared) in.getMethod()).isStatic()) {
					new InvokeMethod(in.getReturn(),null,in.getMethod(),in.getValues(),in.getReplacementObjectParam());
					op.addInfo(in.getInfos());
				}

		//		initializeToNull(ops, in.getParams(), initialized, initializedNull);

				if(in.getReturn() != null)
					initialized[Arrays.asList(refs).indexOf(in.getReturn())] = true;

				ops.add(op);

			}
		}
	      Individual t=new Individual(test.getInitialConstructors(),ops);
	      return t;
	}


}
